package expert

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"gorm.io/gorm"
	"gpt-api/framework/ginplus"
	"gpt-api/framework/log"
	"gpt-api/pkg/model"
	"gpt-api/pkg/pay"
	"gpt-api/pkg/util"
	"strconv"
	"time"
)

func (h *Handler) CoinCharger(c *gin.Context) error {
	var (
		req struct {
			CoinSchemeId uint64      `json:"coin_scheme_id" binding:"required" `
			Channel      pay.Channel `json:"channel" binding:"required"`
			EquipmentId  string      `json:"equipment_id" binding:"required"`
		}

		err error
	)

	if err = c.Bind(&req); err != nil {
		return ginplus.ReplyBadRequest(c, err)
	}

	// 获取充值方案数据
	var coinScheme *model.Coins
	err = h.db.Model(new(model.Coins)).Where("id = ?", req.CoinSchemeId).
		Limit(1).Find(&coinScheme).Error
	if err != nil {
		return ginplus.ReplyInternalError(c, err)
	}

	if coinScheme == nil || coinScheme.ID == 0 {
		return ginplus.ReplyBadRequest(c, errors.New("充值方案匹配异常"))
	}

	// 创建订单
	document := &model.Document{
		Type:        1,
		Amount:      coinScheme.Price,
		EquipmentId: req.EquipmentId,
		Status:      model.DocumentStatusUnPaid,
		DocNumber:   genDocumentNumber(),
	}
	err = h.db.Model(new(model.Document)).Create(&document).Error
	if err != nil {
		return ginplus.ReplyInternalError(c, err)
	}

	params := pay.OrderParams{
		Subject:  "金币充值",
		TradeNo:  document.DocNumber,
		Platform: ginplus.GetPlatform(c),
		Amount:   coinScheme.Price,
	}
	payer, ok := h.payers[req.Channel]
	if !ok {
		return ginplus.ReplyBadRequest(c, errors.New("channel invalid"))
	}
	// 生成订单的充值参数
	orderInfo, err := payer.Order(&params)
	if err != nil {
		return ginplus.ReplyInternalError(c, err)
	}

	return ginplus.ReplyJSON(c, gin.H{"param": orderInfo, "doc_id": document.ID})
}

func (h *Handler) PayStatusNotify(c *gin.Context) error {

	channel, _ := strconv.Atoi("3")
	if channel == 0 {
		channel = 3
	}
	payer, ok := h.payers[pay.Channel(channel)]
	if !ok {
		return ginplus.ReplyBadRequest(c, errors.New("channel invalid"))
	}
	//

	err := payer.Notify(c, h.NotifyCallback)
	if err != nil {
		return ginplus.ReplyInternalError(c, err)

	}
	return nil
}

//NotificationCallback 支付回调

func (h *Handler) PayStatusNotification(c *gin.Context) error {

	channel, _ := strconv.Atoi("3")
	if channel == 0 {
		channel = 3
	}
	payer, ok := h.payers[pay.Channel(channel)]
	if !ok {
		return ginplus.ReplyBadRequest(c, errors.New("channel invalid"))
	}

	err := payer.Notification(c, h.PNotifyCallback)
	if err != nil {
		return ginplus.ReplyInternalError(c, err)

	}
	return nil
}

func (h *Handler) PayStatusWechatNotify(c *gin.Context) error {
	payer, ok := h.payers[pay.WechatChannel]
	if !ok {
		return ginplus.ReplyBadRequest(c, errors.New("channel invalid"))
	}
	err := payer.Notify(c, h.NotifyCallback)
	if err != nil {
		return ginplus.ReplyInternalError(c, err)
	}
	return nil
}

func (h *Handler) NotifyCallback(req *pay.NotifyReq) error {
	return h.db.Transaction(func(tx *gorm.DB) error {
		var document model.Document
		log.Info("查看订单支付状态", log.Var("req", req))
		if req.Mark != 1 {
			var coinScheme model.Coins
			err := h.db.Where("production_id = ?", req.AppleProductID).
				First(&coinScheme).Error
			if err != nil {
				return err
			}
			//从document数据库查询这个订单号是否存在
			var con int64
			err = h.db.Model(new(model.Document)).Where("doc_number = ?", req.TradeNo).Count(&con).Error
			log.Info("查看订单是否存在", log.Var("con", con))
			if err != nil {
				return err
			}
			if con > 0 {
				return nil
			}
			document = model.Document{
				EquipmentId:     req.UserID,
				DocNumber:       req.TradeNo,
				FinishTime:      time.Now().Unix(),
				Status:          model.DocumentStatusPaid,
				Type:            2,
				Amount:          coinScheme.Price,
				OriginalTradeNo: req.OriginalTradeNo,
			}

			if err := tx.Save(&document).Error; err != nil {
				return err
			}

			if req.AppleProductID == "vip.week" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "1").Error
			}
			if req.AppleProductID == "vip.month" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "2").Error
			}
			if req.AppleProductID == "vip.quarter" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "3").Error
			}
			if req.AppleProductID == "vip.year" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "4").Error
			}
			if req.AppleProductID == "vip.forever" {

				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", time.Now().Unix()+100*365*24*3600*1000).
					UpdateColumn("types", "5").Error
			}
		} else {
			err := h.db.Model(new(model.Document)).Where("original_trade_no = ? and equipment_id !='' ", req.OriginalTradeNo).Find(&document).Error

			if err != nil {
				return err
			}

			if req.AppleProductID == "vip.week" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", req.UserID).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "1").Error
			}
			if req.AppleProductID == "vip.month" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", req.UserID).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "2").Error
			}
			if req.AppleProductID == "vip.quarter" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", req.UserID).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "3").Error
			}
			if req.AppleProductID == "vip.year" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", req.UserID).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "4").Error
			}
			if req.AppleProductID == "vip.forever" {

				return tx.Model(&model.Auser{}).Where("equipment_id = ?", req.UserID).
					UpdateColumn("ex_time", time.Now().Unix()+100*365*24*3600*1000).
					UpdateColumn("types", "5").Error
			}
		}

		return nil
	})
}

// 订单单号
func genDocumentNumber() string {
	return fmt.Sprintf("%s%d%s", "GPT", time.Now().UnixNano(), util.RandomCode())
}

func (h *Handler) PNotifyCallback(req *pay.NotifyReq) error {
	return h.db.Transaction(func(tx *gorm.DB) error {
		var document model.Document
		var documentx model.Document
		log.Info("-------1----", log.Var("req", req))
		log.Info("-------2----", log.Var("req", req))
		if req.Channel == pay.AppleChannel {
			var coinScheme model.Coins
			err := h.db.Where("production_id = ?", req.AppleProductID).
				First(&coinScheme).Error
			if err != nil {
				return err
			}
			//从document数据库查询这个订单号是否存在

			err = h.db.Model(new(model.Document)).Where("original_trade_no = ? and equipment_id !='' ", req.OriginalTradeNo).Find(&documentx).Error

			if err != nil {
				return err
			}

			var con int64
			err = h.db.Model(new(model.Document)).Where("doc_number = ? and original_trade_no = ?", req.TradeNo, req.OriginalTradeNo).Count(&con).Error
			log.Info("查看订单是否存在", log.Var("con", con))
			if err != nil {
				return err
			}
			if con > 0 {
				return nil
			}

			document = model.Document{
				EquipmentId:     documentx.EquipmentId,
				DocNumber:       req.TradeNo,
				FinishTime:      time.Now().Unix(),
				Status:          model.DocumentStatusPaid,
				Type:            2,
				Amount:          coinScheme.Price,
				OriginalTradeNo: req.OriginalTradeNo,
			}

			if err := tx.Save(&document).Error; err != nil {
				return err
			}
			if req.AppleProductID == "vip.week" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "1").Error
			}
			if req.AppleProductID == "vip.month" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "2").Error
			}
			if req.AppleProductID == "vip.quarter" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "3").Error
			}
			if req.AppleProductID == "vip.year" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "4").Error
			}
		}

		return nil
	})
}

func (h *Handler) NotifyCallbacks(req *pay.NotifyReq) error {
	return h.db.Transaction(func(tx *gorm.DB) error {
		var document model.Document
		var documentx model.Document
		log.Info("-------1----", log.Var("req", req))
		if req.Channel == pay.AppleChannel {
			var coinScheme model.Coins
			err := h.db.Where("production_id = ?", req.AppleProductID).
				First(&coinScheme).Error
			if err != nil {
				return err
			}
			//从document数据库查询这个订单号是否存在

			err = h.db.Model(new(model.Document)).Where("original_trade_no = ? and equipment_id !='' ", req.OriginalTradeNo).Find(&documentx).Error

			if err != nil {
				return err
			}

			//var con int64
			//err = h.db.Model(new(model.Document)).Where("doc_number = ? and original_trade_no = ?", req.TradeNo, req.OriginalTradeNo).Count(&con).Error
			//log.Info("查看订单是否存在", log.Var("con", con))
			//if err != nil {
			//	return err
			//}
			//if con > 0 {
			//	return nil
			//}

			//document = model.Document{
			//	EquipmentId:     documentx.EquipmentId,
			//	DocNumber:       req.TradeNo,
			//	FinishTime:      time.Now().Unix(),
			//	Status:          model.DocumentStatusPaid,
			//	Type:            2,
			//	Amount:          coinScheme.Price,
			//	OriginalTradeNo: req.OriginalTradeNo,
			//}
			//
			//if err := tx.Save(&document).Error; err != nil {
			//	return err
			//}
			if req.AppleProductID == "vip.week" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "1").Error
			}
			if req.AppleProductID == "vip.month" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "2").Error
			}
			if req.AppleProductID == "vip.quarter" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "3").Error
			}
			if req.AppleProductID == "vip.year" {
				return tx.Model(&model.Auser{}).Where("equipment_id = ?", document.EquipmentId).
					UpdateColumn("ex_time", req.ExTime).
					UpdateColumn("types", "4").Error
			}
		}

		return nil
	})
}
